package com.baitiaojun.user.service.impl;

import com.baitiaojun.api.domain.user.User;
import com.baitiaojun.api.domain.user.UserInfo;
import com.baitiaojun.api.exception.ConditionException;
import com.baitiaojun.api.util.*;
import com.baitiaojun.user.config.AsyncConfig;
import com.baitiaojun.user.feign.ElasticsearchFeign;
import com.baitiaojun.user.feign.MomentsFeign;
import com.baitiaojun.user.mapper.UserInfoMapper;
import com.baitiaojun.user.mapper.UserMapper;
import com.baitiaojun.user.service.*;
import com.baitiaojun.user.support.RedisSupport;
import com.baitiaojun.user.support.UserSupport;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

/**
 * @类名 UserServiceImpl
 * @作者 白条君
 * @创建日期 2022/10/25 19:39
 * @版本 1.0
 */
@Service
public class UserInfoInfoServiceImpl implements UserInfoService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private UserInfoMapper userInfoMapper;

    @Resource
    private RedisSupport redisSupport;

    @Resource
    private UserSupport userSupport;

    @Autowired
    private UserFollowingService userFollowingService;

    @Autowired
    private ElasticsearchFeign elasticsearchFeign;

    @Autowired
    private AsyncConfig asyncConfig;

    @Autowired
    private SystemService systemService;

    @Autowired
    private UserCoinService userCoinService;

    @Autowired
    private MomentsFeign momentsFeign;

    @Autowired
    private UserFansService userFansService;

    @Transactional
    @Override
    public void updateUser(User user, String accessToken) throws Exception {
        Long userId = user.getId();
        String password = user.getPassword();
        String email = user.getEmail();
        User isExsistsUser = userMapper.selectByPrimaryKey(userId);
        if (ObjectUtils.isEmpty(isExsistsUser)) {
            throw new ConditionException("此用户不存在");
        }
        String sign = null;
        if (StringUtils.isNotEmpty(password)) {
            String decrypt;
            try {
                decrypt = RSAUtil.decrypt(password);
            } catch (Exception e) {
                throw new ConditionException("解密失败");
            }
            String salt = String.valueOf(SnowFlakeUtil.getNextId());
            sign = MD5Util.sign(decrypt, salt, ConstantUtil.CHAR_SET_UTF8);
            user.setSalt(salt);
        }
        if (StringUtils.isNotEmpty(email)) {
            if (ObjectUtils.isNotEmpty(userMapper.selectByEmail(email))) {
                throw new ConditionException("此邮箱已被绑定");
            }
            user.setEmail(email);
        }
        user.setPassword(sign);
        user.setUpdatetime(new Date());
        int res = userMapper.updateByPrimaryKeySelective(user);
        if (res == 0) {
            throw new ConditionException("用户系统信息更新失败");
        }
        if (StringUtils.isNotEmpty(password)) {
            systemService.cancellation(accessToken, isExsistsUser.getPhone());
        } else if (StringUtils.isNotEmpty(email)) {
            Object refreshToken = redisSupport.getHash(accessToken, "refreshToken");
            userSupport.addUserToRedis(accessToken, refreshToken, systemService.getUserAndUserInfo(userId));
        }
    }

    @Override
    public void updateUserInfo(UserInfo userInfo, String token) throws Exception {
        Long userInfoId = userInfoMapper.selectByUserId(userInfo.getUserid()).getId();
        if (ObjectUtils.isEmpty(userInfoId)) {
            throw new ConditionException("此用户不存在");
        }
        AESUtil aesUtil = null;
        if (StringUtils.isNotEmpty(userInfo.getAvatar())) {
            aesUtil = AESUtil.lazyGetAesUtil();
            userInfo.setAvatar(aesUtil.decrypt(userInfo.getAvatar()));
        }
        userInfo.setId(userInfoId);
        userInfo.setUpdatetime(new Date());
        int res = userInfoMapper.updateByPrimaryKeySelective(userInfo);
        if (res == 0) {
            throw new ConditionException("用户个人信息更新失败");
        }
        //重新加密avatar字段
        if (StringUtils.isNotEmpty(userInfo.getAvatar())) {
            userInfo.setAvatar(aesUtil.encrypt(userInfo.getAvatar()));
        }
        //保存到userinfo信息redis
        Object refreshToken = redisSupport.getHash(token, "refreshToken");
        userSupport.addUserToRedis(token, refreshToken, systemService.getUserAndUserInfo(userInfo.getUserid()));
        //保存到userinfo信息es
        elasticsearchFeign.saveUserInfo(userInfo);
    }



    @Override
    public Integer getIsExistsUserById(Long id) {
        return userMapper.selectIsExistsUserByPrimaryKey(id);
    }

    @Override
    public List<UserInfo> getUserInfoListByUserId(Set<Long> userIds, Long userId) throws Exception {
        AESUtil aesUtil = AESUtil.lazyGetAesUtil();
        return userInfoMapper.selectUserInfoListByUserIds(userIds).stream().peek(userInfo -> {
            try {
                aesUtil.encrypt(userInfo.getAvatar());
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (ObjectUtils.isNotEmpty(userId)) {
                //我是否关注了这个用户
                if (userIds.size() > 0) {
                    Set<Long> followingIds = userFollowingService.getUserFollowingIdsByUserId(userId);
                    for (Long followingId : followingIds) {
                        if (followingId.equals(userInfo.getId())) {
                            userInfo.setFollowing(true);
                        }
                    }
                }
            }
        }).collect(Collectors.toList());
    }

    @Override
    public UserInfo getUserInfoByUserId(Long userId) throws Exception {
        UserInfo userInfo = userInfoMapper.selectUserInfoByUserId(userId);
        AESUtil aesUtil = AESUtil.lazyGetAesUtil();
        aesUtil.encrypt(userInfo.getAvatar());
        return userInfo;
    }

    @Override
    public User getOtherUser(Long id, Long userId) throws Exception {
        if (ObjectUtils.isEmpty(id)) {
            throw new ConditionException("参数异常");
        }
        UserInfo userInfo = userInfoMapper.selectByPrimaryKey(id);
        if (ObjectUtils.isEmpty(userInfo)) {
            throw new ConditionException("此用户不存在");
        }
        User user = userMapper.selectByPrimaryKey(userInfo.getUserid());
        if (ObjectUtils.isEmpty(userInfo)) {
            throw new ConditionException("此用户不存在");
        }
        AESUtil aesUtil = AESUtil.lazyGetAesUtil();
        userInfo.setAvatar(aesUtil.encrypt(userInfo.getAvatar()));
        //如果是登录用户查看
        if (ObjectUtils.isNotEmpty(userId)) {
            //我是否关注了这个用户
            if (ObjectUtils.isNotEmpty(userId)) {
                Set<Long> followingIds = userFollowingService.getUserFollowingIdsByUserId(userId);
                for (Long followingId : followingIds) {
                    if (followingId.equals(id)) {
                        userInfo.setFollowing(true);
                    }
                }
            }
            userInfo.setUserid(null);
        }
        user.setId(null);
        user.setSalt(null);
        user.setPassword(null);
        userInfo.setBirth(null);
        userInfo.setFollowed(null);
        user.setUserInfo(userInfo);
        return user;
    }

    @Override
    public Long getOtherUserId(Long followingId) {
        return userInfoMapper.selectUserIdById(followingId);
    }

    @Override
    public Set<Long> batchGetUserIdsFollowingIds(Set<Long> followingIds) {
        return userInfoMapper.selectUserIdsFollowingIds(followingIds);
    }

    @Override
    public User getCurrentUserInfo(User user, String token) throws InterruptedException, ConditionException {
        if (ObjectUtils.isEmpty(token)) {
            throw new ConditionException("参数异常");
        }
        Long userId = user.getId();
        if (ObjectUtils.isEmpty(userId)) {
            throw new ConditionException("参数异常");
        }
        //获取线程池
        ThreadPoolExecutor executor = asyncConfig.getAsyncExecutor();
        if (ObjectUtils.isEmpty(executor)) {
            throw new ConditionException("无法获取线程池执行器");
        }
        CountDownLatch latch = new CountDownLatch(4);
        //获取用户硬币数
        AtomicReference<Integer> coinCount = new AtomicReference<>(0);
        executor.execute(() -> {
            Integer count = userCoinService.getUserCoin(userId, token);
            coinCount.set(count);
            latch.countDown();
        });
        //获取用户粉丝数
        Long userInfoId = user.getUserInfo().getId();
        AtomicReference<Integer> fansCount = new AtomicReference<>(0);
        executor.execute(() -> {
            Integer count = userFansService.getFansCount(userInfoId);
            fansCount.set(count);
            latch.countDown();
        });
        //获取用户关注数
        AtomicReference<Integer> followingCount = new AtomicReference<>(0);
        executor.execute(() -> {
            Integer count = userFollowingService.getFollowingCount(userId);
            followingCount.set(count);
            latch.countDown();
        });
        //获取用户动态数
        AtomicReference<Integer> momentsCount = new AtomicReference<>(0);
        executor.execute(() -> {
            Integer count = momentsFeign.getMomentsCount(userId);
            momentsCount.set(count);
            latch.countDown();
        });
        latch.await();
        user.setId(null);
        user.setSalt(null);
        user.setPassword(null);
        UserInfo userInfo = user.getUserInfo();
        userInfo.setCoinCount(coinCount.get());
        userInfo.setFansCount(fansCount.get());
        userInfo.setFollowingCount(followingCount.get());
        userInfo.setMomentsCount(momentsCount.get());
        userInfo.setUserid(null);
        userInfo.setFollowed(null);
        userInfo.setFollowing(null);
        return user;
    }
}